
'use strict';

const createConfig = require('uni-config-center');

const uidConfig = createConfig({
	pluginId: 'uni-id'
});

const db = uniCloud.database();
const dbcmd = db.command;
const wxapi_token_id = 'usemall-wxapi-token';
const wxapi_jsapi_ticket_id = 'usemall-wxapi-jsapi_ticket';

const utils = require('../utils');

// https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html
module.exports = {
	appid: uidConfig.config('h5-weixin.oauth.weixin.appid'),
	message_notify_enabled: uidConfig.config('h5-weixin.message-notify-enabled'),
	// access_token 是公众号的全局唯一接口调用凭据，公众号调用各接口时都需使用access_token，有效期为2个小时
	token: '',
	token_expired: 0,
	
	// jsapi_ticket 是公众号用于调用微信 JS 接口的临时票据，有效期为2个小时
	jsapi_ticket: '',
	jsapi_ticket_expired: 0,
	
	// 获取 access_token
	get_token: async function(valid = false) {
		let res = await db.collection('usemall-token').doc(wxapi_token_id).get();
		const [usemallToken] = res.data;
		if (usemallToken && usemallToken._id && usemallToken.token_expired > Date.now()) {
			if (valid && !await this.valid_token(usemallToken.token)) {
				console.log('valid_token 已失效重新获取');
				await db.collection('usemall-token').doc(wxapi_token_id).update({
					token_expired: 0
				});
				return await this.get_token();
			}
			
			this.token = usemallToken.token;
			this.token_expired = usemallToken.token_expired;
			return this.token;
		}
		
		let url;
		const tokenServer = uidConfig.config('h5-weixin.access-token-server');
		
		if (tokenServer == 'aliyun') {
			// 使用阿里云代理IP模式
			// https://doc.dcloud.net.cn/uniCloud/cf-functions.html#aliyun-eip
			
			/*
			代理服务器IP列表
			
			47.92.132.2
			47.92.152.34
			47.92.87.58
			47.92.207.183
			8.142.185.204
			*/
			
			const appid = uidConfig.config('h5-weixin.oauth.weixin.appid');
			const appsecret = uidConfig.config('h5-weixin.oauth.weixin.appsecret');
			
			url = `https://api.weixin.qq.com/cgi-bin/token`;
			
			res = await uniCloud.httpProxyForEip.get(url, {
				grant_type: "client_credential",
				appid: appid,
				secret: appsecret
			});
			
			console.log('uniCloud.httpProxyForEip.get res', res, typeof res);
			res = JSON.parse(res);
			
			if (res.body && res.body.errcode) {
				console.log('wxapi-token 响应' + res.body.errmsg);
				throw new Error('wxapi-token 响应' + res.body.errmsg);
			}
			
			if (res.body && res.body.access_token) {
				this.token = res.body.access_token;
				this.token_expired = Date.now() + ((res.body.expires_in - 5 * 60) * 1000);
				
				console.log('uniCloud.httpProxyForEip.get get_token', this.token, this.token_expired);
			}
		} else if(tokenServer == 'alipay') {
			// 使用支付宝云IP模式
			
			/*
			服务器IP列表
			
			47.97.38.108
			112.124.10.115
			*/
			
			const appid = uidConfig.config('h5-weixin.oauth.weixin.appid');
			const appsecret = uidConfig.config('h5-weixin.oauth.weixin.appsecret');
			
			url = `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appid}&secret=${appsecret}`;
			res = await utils.http.get(url);
			
			console.log('utils.http.get res', res);
			
			if (res.errcode) {
				throw new Error('wxapi-token 获取失败');
			}
			
			this.token = res.access_token;
			this.token_expired = res.expires_time;
		} else {
			// 使用腾讯云代理IP模式
			url = uidConfig.config('agent.wxapi-token');
			
			if (!url) {
				throw new Error('wxapi-token 请求地址不存在');
			}
			
			// 请求 wxapi token
			res = await utils.http.get(url);
			
			console.log('utils.http.get res', res);
			
			if (res.code !== 200) {
				throw new Error('wxapi-token 获取失败');
			}
			
			this.token = res.datas.access_token;
			this.token_expired = res.datas.expires_time;
		}
		
		
		// 写入最新 token 数据
		await db.collection('usemall-token').doc(wxapi_token_id).set({
			token: this.token,
			token_expired: this.token_expired,
			res: res,
			req: {},
			type: 'wxapi'
		});
		
		return this.token;
	},
	// 验证 access_token
	valid_token: async function(token) {
		const url = 'https://api.weixin.qq.com/cgi-bin/get_api_domain_ip?access_token=' + token;
		
		const res = await utils.http.get(url);
		
		return res.errcode === 0;
	},
	// 获取 jsapi_ticket
	get_jsapi_ticket: async function() {
		let res = await db.collection('usemall-token').doc(wxapi_jsapi_ticket_id).get();
		const [usemallToken] = res.data;
		if (usemallToken && usemallToken._id && usemallToken.jsapi_ticket_expired > Date.now()) {
			this.jsapi_ticket = usemallToken.jsapi_ticket;
			this.jsapi_ticket_expired = usemallToken.jsapi_ticket_expired;
			return this.jsapi_ticket;
		}
		
		// access_token
		const token = await this.get_token(true);
		const url = `https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=${token}&type=jsapi`;
		
		if (!url) {
			throw new Error('wxapi-jsapi_ticket 请求地址不存在');
		}
		
		// 请求 wxapi jsapi_ticket
		res = await utils.http.get(url);
		
		console.log('utils.http.get res', res);
		
		if (res.errcode !== 0) {
			throw new Error(`wxapi-jsapi_ticket 获取失败 ${res.errmsg}`);
		}
		
		this.jsapi_ticket = res.ticket;
		this.jsapi_ticket_expired = Date.now() + (res.expires_in - 60) * 1000;
		
		// 写入最新 token 数据
		await db.collection('usemall-token').doc(wxapi_jsapi_ticket_id).set({
			jsapi_ticket: this.jsapi_ticket,
			jsapi_ticket_expired: this.jsapi_ticket_expired,
			res: res,
			req: {},
			type: 'wxapi'
		});
		
		return this.jsapi_ticket;
	},
	// 获取用户基本信息
	get_userinfo: async function(openid, lang = 'zh_CN') {
		// access_token
		const token = await this.get_token();
		const url = `https://api.weixin.qq.com/cgi-bin/user/info?access_token=${token}&openid=${openid}&lang=${lang}`;
		
		// 发送请求
		const res = await utils.http.get(url);
		console.log('utils.http.get res', res);
		
		if (res.errcode !== 0) {
			throw new Error(`wxapi-get_userinfo 获取失败 ${res.errmsg}`);
		}
		
		return res;
	},
	// 批量获取用户基本信息 最多支持一次拉取100条
	get_userinfos: async function(openids) {
		// access_token
		const token = await this.get_token();
		const url = `https://api.weixin.qq.com/cgi-bin/user/info/batchget?access_token=${token}`;
		
		const data = {
			user_list: []
		};
		
		openids.forEach(x => {
			data.user_list.push({
				openid: x,
				lang: 'zh_CN'
			});
		})
		
		// 发送请求
		const res = await utils.http.post(url, data);
		console.log('utils.http.get res', res);
		
		if (res.errcode !== 0) {
			throw new Error(`wxapi-get_userinfos 获取失败 ${res.errmsg}`);
		}
		
		return res;
	},
	// 创建二维码	https://developers.weixin.qq.com/doc/offiaccount/Account_Management/Generating_a_Parametric_QR_Code.html
	// 	临时二维码 QR_SCENE、QR_STR_SCENE
	// 	永久二维码 QR_LIMIT_SCENE、QR_LIMIT_STR_SCENE
	qrcode_create: async function(data, valid = false) {
		
		// access_token
		const token = await this.get_token(valid);
		const url = `https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=${token}`;
		
		// 发送请求
		const res = await utils.http.post(url, data);
		console.log('utils.http.post res', res);
		
		if (res.errcode) {
			if (res.errcode == 40001) {
				// 令牌失效
				return await this.qrcode_create(data, true);
			}
			
			throw new Error(`wxapi-qrcode_create 创建失败 ${res.errmsg}`);
		}
		
		// 二维码图片地址
		res.qrcode = `https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=${res.ticket}`;
		
		return res;
	},
	// 创建临时二维码
	qrcode_create_temp: async function(value, expire_seconds = 86400) {
		const data = {
			// 二维码有效时间，以秒为单位。 最大不超过2592000（即30天）
			expire_seconds: expire_seconds,
			action_name: '', 
			action_info: {
				scene: {}
			}
		};
		
		if (typeof value === 'number') {
			// QR_SCENE为临时的整型参数值
			data.action_name = 'QR_SCENE';
			// 场景值ID，临时二维码时为32位非0整型
			data.action_info.scene.scene_id = value;
		} else {
			// QR_STR_SCENE为临时的字符串参数值
			data.action_name = 'QR_STR_SCENE';
			// 场景值ID（字符串形式的ID），字符串类型，长度限制为1到64
			data.action_info.scene.scene_str = value;
		}
		
		return await this.qrcode_create(data);
	},
	// 创建永久二维码
	qrcode_create_limit: async function(value) {
		const data = {
			action_name: '', 
			action_info: {
				scene: {}
			}
		};
		
		if (typeof value === 'number') {
			// QR_LIMIT_SCENE为永久的整型参数值
			data.action_name = 'QR_LIMIT_SCENE';
			// 场景值ID，临时二维码时为32位非0整型
			data.action_info.scene.scene_id = value;
		} else {
			// QR_LIMIT_STR_SCENE为永久的字符串参数值
			data.action_name = 'QR_LIMIT_STR_SCENE';
			// 场景值ID（字符串形式的ID），字符串类型，长度限制为1到64
			data.action_info.scene.scene_str = value;
		}
		
		return await this.qrcode_create(data);
	},
	
	// 推送模板消息
	send_tpl: async function(openid, tplid, req, valid = false) {
		const token = await this.get_token(valid);
	
		const url = `https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=${token}`;
	
		// 发送 post 请求
		const res = await utils.http.post(url, {
			"touser": openid,
			"template_id": tplid,
			...req
		});
		
		if (res.errcode == 40001) {
			// 令牌失效
			return await this.send_tpl(openid, tplid, req, true);
		}

		return res;
	}
	
}
